#include "cppjieba/Jieba.hpp"
#include "Configuration.h"
#include "Singleton.hpp"
#include "SplitTool.h"
#include <cctype>
#include <set>
#include <sstream>
#include <vector>

using namespace NATSUME;


SplitToolCppJieba::SplitToolCppJieba(Configuration * conf)
    : m_pConf(conf) 
{ 
    auto         map                    = m_pConf->getConfigMap();
    // 最大概率法(MPSegment: MAX Probability) 分词所使用的词典路径
    const char * const DICT_PATH        = map["DICT_PATH"].c_str();
    // 隐式马尔科夫模型(HMMSegment: Hidden Markov Model) 分词所使用的词典路径
    const char * const HMM_PATH         = map["HMM_PATH"].c_str();
    // 用户自定义词典路径
    const char * const USER_DICT_PATH   = map["USER_DICT_PATH"].c_str();
    // IDF路径
    const char * const IDF_PATH         = map["IDF_PATH"].c_str();
    // 停用词路径
    const char * const STOP_WORD_PATH   = map["STOP_WORD_PATH"].c_str();

    // 使用单例模式模板类, 来创建cppJieba::Jieba类
    m_pJieba = Singleton<cppjieba::Jieba>::getInstance(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH);
}

SplitToolCppJieba::~SplitToolCppJieba() { }



std::vector<std::string>
SplitToolCppJieba::cutCN(const std::string & sentence) {
    // words: 存储分词后的结果
    std::vector<std::string>    words, result;
   
    // 对sentence句子进行分词
    m_pJieba->Cut(sentence, words);

    // 中文停用词集
    std::set<std::string> stopWordList = m_pConf->getCN_StopWordList();
    // 进行停用词集去重
    DISTINCT_StopWord(words, result, stopWordList);
    
    return result;
}

std::vector<std::string>
SplitToolCppJieba::cutEN(const std::string & sentence) {
    std::vector<std::string>    result;
    std::stringstream           line(sentence);
    std::string                 word;
    // 英文停用词集
    std::set<std::string>       stopWordList    = m_pConf->getEN_StopWordList();
    
    while (line >> word) {
        auto it = stopWordList.find(word);
        if (it == stopWordList.end()) 
            result.emplace_back(word);
    }

    return result;
}



SplitTool * SplitToolManager::create(Configuration *conf) {
    if (conf) {
        SplitTool   *pSplitTool = new SplitToolCppJieba(conf);
        return pSplitTool;
    }

    return nullptr;
}

void SplitToolManager::destroy(SplitTool *pSplitTool) {
    if (pSplitTool) {
        delete pSplitTool;
        pSplitTool = nullptr;
    }
}